﻿// ****************************************************************
// Copyright 2012, Stephan Burguchev
// e-mail: me@sburg.net
// ****************************************************************
// *
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using NUnit.Framework;
using Updater.Common;
using Updater.Sources;
using Updater.Updates;
using Version = Updater.Utils.Version;

namespace Updater.Tests
{
    [TestFixture]
    public class UpdateManagerTests
    {
        private TestDataProvider _dataProvider;
        private TempDirectory _tempDirectory;

        [SetUp]
        public void SetUp()
        {
            this._tempDirectory = new TempDirectory();
            this._dataProvider = new TestDataProvider(this._tempDirectory);
        }

        [TearDown]
        public void TearDown()
        {
            this._tempDirectory.Dispose();
        }

        [Test]
        public void TestCompleteUpdateCycle()
        {
            // Arrange
            File.Copy(
                Path.Combine(Config.TestDataDirectory, "nop.exe"),
                Path.Combine(this._dataProvider.ApplicationDirectory, "nop.exe"),
                true);

            string rssTemplate = Path.Combine(Config.TestDataDirectory, "update-manager-test-rss.xml");
            XDocument xdoc = XDocument.Load(rssTemplate);
            XAttribute[] urls = xdoc.Root.Element("channel").Elements("item")
                                    .Select(item => item.Element("enclosure").Attribute("url")).ToArray();
            urls[0].Value = "file:///" + Path.Combine(Config.TestDataDirectory, "zip-archive-update.zip").Replace('\\', '/');
            urls[1].Value = "file:///" + Path.Combine(Config.TestDataDirectory, "zip-archive-update-2.zip").Replace('\\', '/');
            string updatesRssLocation = Path.Combine(this._tempDirectory, "updates-rss.xml");
            xdoc.Save(updatesRssLocation);

            var updatesFeedUri = new Uri("file:///" + updatesRssLocation.Replace('\\', '/'));
            var configuration = new Configuration
                {
                    UpdatesFeedUri = updatesFeedUri,
                    ApplicationDirectory = this._dataProvider.ApplicationDirectory,
                    UpdaterCacheDirectory = this._dataProvider.UpdaterCacheDirectory,
                    CurrentVersion = Version.Parse("1.0.0.0"),
                    ApplicationFilename = "nop.exe"
                };
            var source = new WebSource();
            var reader = new UpdatesRssFeedReader();
            var updateManager = new UpdateManager(configuration, source, reader);

            // Act
            Assert.True(updateManager.CheckForUpdates());
            updateManager.Download();
            updateManager.Prepare();
            Assert.True(updateManager.ApplyUpdatesAfterExit(true));

            // configuration.ApplicationFilename is the expected name of a temporary created updater executable.
            Process[] processes = Process.GetProcessesByName(
                Path.GetFileNameWithoutExtension(configuration.ApplicationFilename));
            foreach (Process process in processes)
            {
                process.WaitForExit();
            }

            // Assert
            FileAssert.AreEqual(
                Path.Combine(this._dataProvider.ApplicationDirectory, "empty-1.data"),
                Path.Combine(Config.TestDataDirectory, "empty.data"));
            FileAssert.AreEqual(
                Path.Combine(this._dataProvider.ApplicationDirectory, "empty-2.data"),
                Path.Combine(Config.TestDataDirectory, "empty.data"));
            Assert.True(Directory.Exists(Path.Combine(this._dataProvider.ApplicationDirectory, "TestSubdir2")));
            FileAssert.AreEqual(
                Path.Combine(this._dataProvider.ApplicationDirectory, "1kb.data"),
                Path.Combine(Config.TestDataDirectory, "1kb.data"));
            FileAssert.AreEqual(
                Path.Combine(this._dataProvider.ApplicationDirectory, "512kb.data"),
                Path.Combine(Config.TestDataDirectory, "512kb.data"));
            FileAssert.AreEqual(
                Path.Combine(this._dataProvider.ApplicationDirectory, "TestSubdir2\\1kb.data"),
                Path.Combine(Config.TestDataDirectory, "TestSubdir\\TestSubdir2\\1kb.data"));
            FileAssert.AreEqual(
                Path.Combine(this._dataProvider.ApplicationDirectory, "TestSubdir2\\512kb.data"),
                Path.Combine(Config.TestDataDirectory, "TestSubdir\\TestSubdir2\\512kb.data"));
        }
    }
}
